package core;

import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

public abstract class VectorialObject implements Object2D, Selectable {

	private static final Double VERTICE_SIZE = 5.0;
	
	protected List<Point3D> mVertices;
	
	protected Rectangle2D.Double rect;
	
	private boolean selected = false;
	
	protected Point3D minPoint = new Point3D(999999999, 999999999);
	
	protected Point3D maxPoint = new Point3D(0, 0);
	
	public VectorialObject() {
		mVertices = new ArrayList<Point3D>();
		rect = new Rectangle2D.Double();	
		rect.width = VERTICE_SIZE;
		rect.height = VERTICE_SIZE;
	}
	
    @Override
	public void draw(OurGraphics g2) {
	}

	public void move(int dx, int dy) {
    	
    	double[][] move = {{1, 0, 0},
    	                   {0, 1, 0},
    	                   {dx, dy, 1}}; 
    	
    	Matrix matrix = new Matrix(move);
    	
		for(Point3D p : mVertices) {
			Matrix.mult(p, matrix);
		}
		
		update();
    }
    
    public void rotate(int x, int y, int teta ) {
    	
    	double radiano = Math.toRadians(teta);
    	double cos = Math.cos(radiano);
    	double sin = Math.sin(radiano);
    	
    	double[][] rotate = {{cos, sin, 0},
			                 {-1*sin,    cos, 0},
			                 {(-1*x*cos)+(y*sin)+(x), (-x*sin)-(y*cos)+(y), 1}}; 
  
    	Matrix matrix = new Matrix(rotate);

		for(Point3D p : mVertices) {
			Matrix.mult(p, matrix);
		}
		
		update();
    }
    
    public void resize(float x, float y) {
    
    	double[][] resize = {{x, 0, 0},
			                 {0, y, 0},
			                 {x*-1*(minPoint.getX()) + minPoint.getX(), y*-1*(minPoint.getY()) + minPoint.getY(), 1}};
    	
    	Matrix matrix = new Matrix(resize);
    	
		for(Point3D p : mVertices) {
			Matrix.mult(p, matrix);
		}
		
		update();
    }
    
    public abstract void clipping(int xMin, int yMin, int xMax, int yMax );
	
    public void update() {
    	resetMinMax();
    	recalcMinMax();
    }
    
    public Point3D getCenter() {
    	
    	Point3D pCenter = new Point3D(0, 0);
    	
    	pCenter.setX((minPoint.getX() + maxPoint.getX())/2);
    	pCenter.setY((minPoint.getY() + maxPoint.getY())/2);
    	
    	return pCenter;
    }
    
	protected void drawSelectionSquare(OurGraphics o){
		o.setLinePattern(5);
		o.setColor(Color.LIGHT_GRAY);
		o.drawSquare((int)(minPoint.getX() - VERTICE_SIZE/2),
					 (int)(minPoint.getY() - VERTICE_SIZE/2),
					 (int)(maxPoint.getX() + VERTICE_SIZE/2),
					 (int)(maxPoint.getY() + VERTICE_SIZE/2));
		o.setLinePattern(OurGraphics.NO_DASH);
	}
	
	protected void resetMinMax() {
		minPoint.setX(999999999);
		minPoint.setY(999999999);
		maxPoint.setX(0);
		maxPoint.setY(0);
	}
	
	protected void recalcMinMax() {
		for(Point3D p : mVertices) {
			checkMinMax(p);
		}
	}
	
	protected void checkMinMax(Point3D p) {
		if(p.getX() < minPoint.getX()){
			minPoint.setX(p.getX());
		}
		
		if(p.getY() < minPoint.getY()) {
			minPoint.setY(p.getY());
		}
		
		if(p.getX() > maxPoint.getX()){
			maxPoint.setX(p.getX());
		}
		
		if(p.getY() > maxPoint.getY()) {
			maxPoint.setY(p.getY());
		}
	}
	
	protected void drawVertice(Point3D pt, OurGraphics g2) {
		
		if(!selected) return;
		
		rect.x = pt.getX() - VERTICE_SIZE/2;
		rect.y = pt.getY() - VERTICE_SIZE/2;
		g2.getRealGraphics().setColor(Color.LIGHT_GRAY);
		g2.getRealGraphics().fill(rect);
	}
	
	public abstract boolean intersect(Point3D pt);
	
	public void addVertice(Point3D pt) {
		mVertices.add(pt);
		checkMinMax(pt);
	}
		
		
	public Point3D getVertice(int v) {
		return mVertices.get(v);
	}

	@Override
	public boolean isSelected() {
		return selected;
	}

	@Override
	public void setSelected(boolean b) {
		selected = b;
	}
	
	public int getVerticeCount() {
		return mVertices.size();
	}
	
}
